<template>
  <o-modal
    v-model="isShow"
    :title="config.modalTitle"
    :size="config.modalSize || [560, 420]"
    :mask="true"
    :tap-close="false"
    :show-footer="true"
    @on-close="close"
  >
    <div slot="content" class="slot-container">
      <div id="main"></div>
      <!-- <o-card-box :isExpand="false" :width="400">
        <vxe-grid
          ref="xGrid"
          v-bind="gridOptions"
          @page-change="pageChange"
        ></vxe-grid>
      </o-card-box> -->
    </div>
  </o-modal>
</template>

<script lang="ts">
import oModal from '@/components/base/modal/o-modal/index.vue';
import { Component, Prop, Vue } from 'vue-property-decorator';
import { Tsrv, getGridOptions } from './config';

const echarts = require('echarts');

interface config {
  modalTitle?: string;
  modalSize?: Array<number>;
  config?: any;
}

@Component({
  components: {
    oModal
  }
})
export default class oChartReport extends Vue {
  /**
   * props
   */
  @Prop() config: config;

  @Prop() id: number;

  /**
   * data
   */
  private isShow: boolean = false;

  private split: number = 0.6;

  public gridOptions = getGridOptions();

  private chartRender: any = null;

  private chartOption: any = null;

  private chartContainerHtml: any;

  private reqParam: any = null;

  private markLine: Array<any> = [];

  created() {
    this.show();
    this.init();
  }

  mounted() {
    const charDom = document.getElementById('main');
    this.chartRender = echarts.init(charDom);
    this.setEchartsData();
    this.$nextTick(() => {
      const erd = this.$elementDetecter();
      erd.listenTo(charDom, (el: any) => {
        this.chartResize();
      });
    });
  }

  private init() {
    this.reqParam = Tsrv.utils.clone(
      this.config?.config?.dataSource?.params,
      true
    );
    this.setPage();
  }

  private setPage() {
    if (!Tsrv.noValue(this.reqParam?.pageNo)) {
      this.reqParam.pageNo = this.gridOptions.pagerConfig.currentPage;
    }
    if (!Tsrv.noValue(this.reqParam?.pageSize)) {
      this.reqParam.pageSize = this.gridOptions.pagerConfig.pageSize;
    }
  }

  private setEchartsData() {
    const reqConfig = this.config.config?.config;
    this.chartOption = {
      animation: false,
      grid: {
        top: 40,
        left: 50,
        right: 40,
        bottom: 50
      },
      xAxis: {
        name: 'x',
        minorTick: {
          show: true
        },
        minorSplitLine: {
          show: true
        }
      },
      yAxis: {
        name: 'y',
        min: -100,
        max: 100,
        minorTick: {
          show: true
        },
        minorSplitLine: {
          show: true
        }
      },
      dataZoom: [
        {
          show: true,
          type: 'inside',
          filterMode: 'none',
          xAxisIndex: [0],
          startValue: -20,
          endValue: 20
        },
        {
          show: true,
          type: 'inside',
          filterMode: 'none',
          yAxisIndex: [0],
          startValue: -20,
          endValue: 20
        }
      ],
      series: [
        {
          type: 'line',
          showSymbol: false,
          clip: true,
          data: this.generateData()
        }
      ]
    };
    this.chartOption && this.chartRender.setOption(this.chartOption);
  }

  private func(x: number) {
    x /= 10;
    return Math.sin(x) * Math.cos(x * 2 + 1) * Math.sin(x * 3 + 2) * 50;
  }

  private generateData() {
    const data = [];
    for (let i = -200; i <= 200; i += 0.1) {
      data.push([i, this.func(i)]);
    }
    return data;
  }

  private handleEChartConfig() {
    const reqConfig = this.config.config?.config;
    if (!Tsrv.noValue(reqConfig)) {
      // this.chartOption
      // yAxis 相关配置
      if (!Tsrv.noValue(reqConfig?.yAxis)) {
        const yAxis = reqConfig.yAxis;

        if (
          !Tsrv.noValue(yAxis?.markLines) &&
          !Tsrv.noValue(this.chartOption?.series)
        ) {
          const markLines = yAxis.markLines;
          const series = this.chartOption.series;
          markLines.forEach((el, i) => {
            const find = series.find(it => it.name === el?.type);
            if (!Tsrv.noValue(find) && !Tsrv.noValue(el?.lines)) {
              const data = [];
              const lines = el.lines;
              lines.forEach((e: any, ii: number) => {
                const d = {
                  name: e?.label ?? '装饰线',
                  yAxis: e?.value ?? 0,
                  lineStyle: {
                    color: `rgb(${Math.floor(
                      Math.random() * 256
                    )}, ${Math.floor(Math.random() * 256)}, ${Math.floor(
                      Math.random() * 256
                    )})`
                  }
                };
                data.push(d);
              });
              series[el.type]['markLine'] = {
                silent: true, // 不触发事件
                symbol: 'none', // 去掉箭头
                label: {
                  position: 'middle', // 标签位置
                  formatter: ({ name, value }) => `${name}: ${value}` // 自定义标签格式
                },
                lineStyle: {
                  type: 'dashed', // 虚线样式
                  width: 2
                },
                data
              };
            }
          });
        }
      }
    }
  }

  /**
   * pageChange 翻页
   */
  private pageChange(e: any) {
    if (
      this.gridOptions.pagerConfig.currentPage !== e.currentPage ||
      this.gridOptions.pagerConfig.pageSize !== e.pageSize
    ) {
      this.gridOptions.pagerConfig.currentPage = e.currentPage;
      this.gridOptions.pagerConfig.pageSize = e.pageSize;
      this.setPage();
      this.loadChartData();
    }
  }

  private loadChartData() {
    const reqConfig = this.config.config;
    this.getChartData().then(([resp, err]) => {
      if (err) {
        this.$msg(err);
        // this.setEchartsData([], []);
        this.setEchartsData();
        return;
      }
      const chartData = resp?.data;
      if (!Tsrv.noValue(chartData) && Array.isArray(chartData)) {
        // 先按时间排序
        const sortedData = [...chartData].sort(
          (a, b) => new Date(a.name).getTime() - new Date(b.name).getTime()
        );
        this.gridOptions.pagerConfig.total = sortedData.length;
        const grid: any = this.$refs.xGrid;
        grid.reloadData(sortedData);
        const xData = [
          // ...new Set(sortedData.map(it => new Date(it?.name).toLocaleString()))
          ...new Set(sortedData.map(it => it?.name))
        ];
        const groupData = Tsrv.utils.groupBy(sortedData, 'type');
        const series = [];
        Object.keys(groupData).forEach(it => {
          const yD = [];
          for (let i = 0; i < xData.length; i++) {
            const el = xData[i];
            const find = groupData[it].find(f => f['name'] === el);
            if (Tsrv.noValue(find)) {
              // yD[i] = undefined;
              yD[i] = 0;
            } else {
              yD[i] = Number(find['value']);
            }
          }
          series.push({
            name: it,
            type: 'line',
            symbol: 'none',
            sampling: 'lttb',
            itemStyle: {
              color: `rgb(${Math.floor(Math.random() * 256)}, ${Math.floor(
                Math.random() * 256
              )}, ${Math.floor(Math.random() * 256)})`
            },
            data: yD
          });
        });
        // this.setEchartsData(xData, yData);
        this.setEchartsData();
      } else {
        this.gridOptions.pagerConfig.total = 0;
        const grid: any = this.$refs.xGrid;
        grid.reloadData([]);
        this.setEchartsData();
      }
    });
  }

  private getChartData(): Promise<any> {
    const reqConfig = this.config.config;
    let param = Tsrv.utils.clone(this.reqParam, true);
    if (Tsrv.noValue(reqConfig?.dataSource?.url))
      return Promise.resolve([null, 'no url']);
    if (
      Tsrv.noValue(this.reqParam) ||
      Object.keys(this.reqParam).length === 0
    ) {
      param = {};
    }
    if (reqConfig?.dataSource?.method === 'post') {
      return Tsrv.standardPostReq<any, any>(param, reqConfig.dataSource.url);
    }
    let url: string = Tsrv.utils.clone(reqConfig.dataSource.url);
    if (!Tsrv.noValue(param) && Object.keys(param).length > 0) {
      url = url.concat('?');
      const ps = Object.keys(param);
      for (let i = 0; i < ps.length; i++) {
        if (i === ps.length - 1) {
          url = url.concat(`${ps[i]}=${param[ps[i]]}`);
        } else {
          url = url.concat(`${ps[i]}=${param[ps[i]]}&`);
        }
      }
    }
    return Tsrv.standardGetReq<any, any>({}, url);
  }

  private chartResize() {
    if (this.chartRender) {
      this.chartRender.resize();
    }
  }

  public show() {
    this.isShow = true;
  }

  public hide() {
    this.isShow = false;
  }

  public confirm() {
    this.$bus.$emit(`modal_${this.id}`, 'test');
    this.hide();
  }

  public close() {
    this.$bus.$emit(`modal_${this.id}`);
    this.hide();
  }
}
</script>

<style lang="scss" scoped>
.slot-container {
  width: 100%;
  height: 100%;

  #main {
    width: 100%;
    height: 100%;
  }
}
</style>
